import 'dart:math';
import 'package:flutter/material.dart';

class XSticky extends StatefulWidget {
  List<String> sliverMod;
  List<Widget> slivers;
  List<int> listCount;
  List<Map<String,double>> stickyHeight;

  XSticky({
    required this.sliverMod, // sliverMod与slivers搭配使用 举例：['view','sticky','list']
    required this.slivers, // 如果sliverMod如上配置，则slivers格式为：[Container(),Container(),(context, index) {return Container()}]
    this.listCount = const [], // 当sliverMod有list时，请填写listCount
    this.stickyHeight = const [], // 当sliverMod有sticky时，请填写stickyHeight,举例[{'minHeight':50,'maxHeight':50}]
  });

  @override
  State<StatefulWidget> createState() {
    return _xStickyState();
  }
}

class _xStickyState extends State<XSticky> {
  List<Widget> slivers = [];

  @override
  void initState() {
    super.initState();
    renderView();
  }

  renderView(){
    slivers = [];
    int listCount_index = 0;
    int stickyHeight_index = 0;
    for(int index=0;index<widget.sliverMod.length;index++){
      switch(widget.sliverMod[index]){
        case 'view':
          slivers.add(_buildView(widget.slivers[index]));
          break;
        case 'sticky':
          slivers.add(_buildSticky(widget.slivers[index],widget.stickyHeight[stickyHeight_index]));
          stickyHeight_index++;
          break;
        case 'list':
          slivers.add(_buildList(widget.slivers[index],widget.listCount[listCount_index]));
          listCount_index++;
          break;
      }
    }
  }

  @override
  Widget build(BuildContext context) {
    return CustomScrollView(
      slivers: slivers,
    );
  }

  Widget _buildView(child) {
    //在使用CustomScrollView创建自定义滚动效果的时候，CustomScrollView只能包含sliver系列组件，如果包含普通的组件如何处理？使用SliverToBoxAdapter包裹
    return SliverToBoxAdapter(
      child: child,
    );
  }

  Widget _buildSticky(child,height) {
    return SliverPersistentHeader(
      pinned: true, //是否固定在顶部
      floating: true,
      delegate: _SliverAppBarDelegate(
        minHeight: height['minHeight'], //收起的高度
        maxHeight: height['maxHeight'], //展开的最大高度
        child: child,
      )
    );
  }

  Widget _buildList(child,count) {
    return SliverList(
      delegate: SliverChildBuilderDelegate((context, index) {
        return child;
      },
      childCount: count,
    ));
  }

  @override
  void dispose() {
    super.dispose();
  }
}

class _SliverAppBarDelegate extends SliverPersistentHeaderDelegate {
  _SliverAppBarDelegate({
    required this.minHeight,
    required this.maxHeight,
    required this.child,
  });

  final double minHeight;
  final double maxHeight;
  final Widget child;

  @override
  double get minExtent => minHeight;

  @override
  double get maxExtent => max(maxHeight, minHeight);

  @override
  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
    return new SizedBox.expand(child: child);
  }

  @override
  bool shouldRebuild(_SliverAppBarDelegate oldDelegate) {
    return maxHeight != oldDelegate.maxHeight ||
        minHeight != oldDelegate.minHeight ||
        child != oldDelegate.child;
  }
}